#ifndef INC_TOOL_H
#define INC_TOOL_H

#include "../base/MouseListener.h"
#include "DiagramFam.h"
#include "DiagramMan.h"

/**
 * ABC for all Tools with which the user creates the diagram.
 */
class Tool : public MouseListener
{
	public:
		Tool(DiagramMan&);

		/*** MouseListener functions ***/

		// note to subclasses: don't override these!
		bool mouseMoveEvent(QMouseEvent&);
		bool mousePressEvent(QMouseEvent&);
		bool mouseReleaseEvent(QMouseEvent&);

	protected:
		DiagramMan& dman() const;

		/**
		 * Convenience function to translate given point to logical coordinates.
		 * Equivalent to:
		 *
		 * dman().active().canvas().trans().tological(pt)
		 */
		QPoint tological(const QPoint& pt) const;

		/*** MOUSE MOVEMENT TEMPLATE FUNCTIONS ***/

		/**
		 * Called when mouse is pressed. If the subclass handles this, then it
		 * will not receive a click() notification from the same event.
		 * @return true if the implementation handled the press
		 */
		virtual bool press(QMouseEvent&);

		/**
		 * Called when mouse is pressed and released in same location.
		 */
		virtual void click(QMouseEvent&) = 0;

		/**
		 * Called when the mouse is moved while not dragging.
		 */
		virtual void move(QMouseEvent&);

		/**
		 * Called when user first moves mouse while holding left button down.
		 * The QPoint is (historical) position of the mouse when the left button
		 * was first clicked.
		 *
		 * Note: drag() will be called immediately after this to update the
		 * mouse position.
		 */
		virtual void startDrag(QPoint& initialPosition) = 0;

		/**
		 * Called during a drag so that the tool can, e.g., update the user
		 * interface.
		 */
		virtual void drag(QMouseEvent&) = 0;

		/**
		 * Called when the user releases the mouse from a drag.
		 */
		virtual void endDrag(QMouseEvent&) = 0;

	private:
		DiagramMan& _dman;
		bool _dragging;
		QPoint _initialPress;
		bool _pressHandled;
};

inline QPoint Tool::tological(const QPoint& pt) const
{
	return dman().active().canvas().trans().tological(pt);
}

#endif // INC_TOOL_H

